package com.ydd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ydd.dto.SysRoleQueryDTO;
import com.ydd.dto.SysRoleUpdateDTO;
import com.ydd.entity.SysMenu;
import com.ydd.entity.SysRole;
import com.ydd.entity.SysRoleMenu;
import com.ydd.mapper.MenuMapper;
import com.ydd.mapper.SysRoleMapper;
import com.ydd.mapper.SysRoleMenuMapper;
import com.ydd.result.PageResult;
import com.ydd.service.SysRoleService;
import com.ydd.vo.SysMenuChildVO;
import com.ydd.vo.SysRoleMenuVO;
import com.ydd.vo.SysRoleQueryVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Autowired
    private MenuMapper menuMapper;

    @Override
    public PageResult page(SysRoleQueryDTO sysRoleQueryDTO) {
        //1.设置分页查询参数
        PageHelper.startPage(sysRoleQueryDTO.getPage(), sysRoleQueryDTO.getLimit());
        //2.调用sysRoleMapper进行分页查询，添加条件为角色名模糊查询，返回rolelist的集合
        Page<SysRole> page = sysRoleMapper.pageQuery(sysRoleQueryDTO.getName());
        List<SysRole> roleList = page.getResult();
        //3.调用sysRoleMenuMapper进行遍历查询，返回一个RoleMenu的集合
        List<SysRoleQueryVO> sysRoleQueryVOList = new ArrayList<>();
        for (SysRole role : roleList) {
            List<SysRoleMenu> menuList = sysRoleMenuMapper.getMenuById(role.getId());
            List<String> menuIdList = menuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
            String menuIdStr = StringUtils.join(menuIdList, ",");
            SysRoleQueryVO sysRoleQueryVO = new SysRoleQueryVO();
            BeanUtils.copyProperties(role, sysRoleQueryVO);
            sysRoleQueryVO.setRoleId(role.getId());
            sysRoleQueryVO.setRoleMenus(menuIdStr);
            sysRoleQueryVOList.add(sysRoleQueryVO);
        }

        return PageResult.builder()
                .currentPage(sysRoleQueryDTO.getPage())
                .data(sysRoleQueryVOList)
                .pageSize(sysRoleQueryDTO.getLimit())
                .totalPages(page.getPages())
                .count(page.getTotal())
                .build();
    }

    /**
     * 根据id查询角色
     *
     * @param id
     * @return
     */
    @Override
    public SysRoleMenuVO getById(String id) {
        SysRoleMenuVO sysRoleMenuVO = new SysRoleMenuVO();

        // 获取角色数据
        SysRole role = sysRoleMapper.getById(id);
        // 将角色数据封装至vo
        BeanUtils.copyProperties(role, sysRoleMenuVO);

        // 获取对应中间表集合
        LambdaQueryWrapper<SysRoleMenu> roleMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleMenuLambdaQueryWrapper.eq(SysRoleMenu::getRoleId, id);
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectList(roleMenuLambdaQueryWrapper);

        // 遍历中间表 获取该角色所具备的所有menu对象
        List<SysMenu> allMenus = new ArrayList<>();
        for (SysRoleMenu sysRoleMenu : sysRoleMenus) {
            LambdaQueryWrapper<SysMenu> menuQueryWrapper = new LambdaQueryWrapper<>();
            menuQueryWrapper.eq(SysMenu::getId, sysRoleMenu.getMenuId());
            SysMenu sysMenu = menuMapper.selectOne(menuQueryWrapper);
            allMenus.add(sysMenu);
        }

        // 开始封装第一层
        // 定义出autuList集合
        List<SysMenuChildVO> autuDTOList = new ArrayList<>();

        // 开始封装第一层
        for (SysMenu menu : allMenus) {
            SysMenuChildVO firstMenu = new SysMenuChildVO();
            if (menu.getPid() == 0) {
                // 此时为最外层按钮
                BeanUtils.copyProperties(menu, firstMenu);
                autuDTOList.add(firstMenu);
            }

        }

        // 方法递归 封装所有子集
        sysRoleMenuVO.setAuthList(setCh(0, allMenus));
        return sysRoleMenuVO;
    }

    /**
     * 递归算法
     *
     * @param pid
     * @param sysMenus
     * @return
     */
    public Object[] setCh(Integer pid, List<SysMenu> sysMenus) {
        List<SysMenuChildVO> father = new ArrayList<>();
        for (SysMenu sysMenu : sysMenus) {
            if (sysMenu.getPid().equals(pid)) {
                SysMenuChildVO child = new SysMenuChildVO();
                SysMenu fatherMenu = menuMapper.selectById(sysMenu.getId());
                BeanUtils.copyProperties(fatherMenu, child);
                child.setChildren(setCh(child.getId(), sysMenus));
                father.add(child);
            }
        }
        return father.toArray();
    }


    /**
     * 角色删除
     *
     * @param id
     */
    @Override
    public void delById(String id) {
        sysRoleMapper.delById(id);
    }


    /**
     * 角色列表-全部
     *
     * @return
     */
    @Override
    public List<SysRole> listRole() {
        return sysRoleMapper.list();
    }

    /**
     * 角色修改
     *
     * @param sysRoleUpdateDTO
     */
    @Override
    @Transactional
    public void update(SysRoleUpdateDTO sysRoleUpdateDTO) {
        String roleId = sysRoleUpdateDTO.getId();
        sysRoleMapper.update(roleId, sysRoleUpdateDTO.getName(), sysRoleUpdateDTO.getDescription());
        String[] menuids = sysRoleUpdateDTO.getMenuids();
        //清空角色id的所有权限
        sysRoleMenuMapper.deleteId(roleId);
        //批量插入角色权限
        for (int i = 0; i < menuids.length; i++) {
            sysRoleMenuMapper.insertMenu(roleId, menuids[i]);
        }
    }

    /**
     * 角色添加
     *
     * @param sysRoleUpdateDTO
     */
    @Override
    @Transactional
    public void add(SysRoleUpdateDTO sysRoleUpdateDTO) {
        SysRole sysRole = new SysRole();
        sysRole.setName(sysRoleUpdateDTO.getName());
        sysRole.setDescription(sysRoleUpdateDTO.getDescription());
        sysRole.setCreateDate(LocalDateTime.now());
        sysRoleMapper.insert(sysRole);
        String roleId = sysRoleMapper.selectByName(sysRoleUpdateDTO.getName());
        String[] menuids = sysRoleUpdateDTO.getMenuids();
        for (int i = 0; i < menuids.length; i++) {
            sysRoleMenuMapper.insertMenu(roleId, menuids[i]);
        }
    }
}
